package cn.brilliantfuture.commentry.lockers.impl;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.UserTransaction;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;

import cn.brilliantfuture.commentry.entity.Lockers;
import cn.brilliantfuture.commentry.entity.Purchaser;
import cn.brilliantfuture.commentry.entity.StorageServiceInfo;
import cn.brilliantfuture.commentry.lockers.StorageServiceMessageLocal;
import cn.brilliantfuture.commentry.util.CRC8;
import cn.brilliantfuture.commentry.util.CommEntryUtil;
import cn.brilliantfuture.commentry.util.DateTimeHelper;

/**
 * 
 * Title: Communication Entry
 * 
 * Author:  LiTian  
 *
 * Date: 2012-10-24
 * 
 * Description:
 * 
 */
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class StorageServiceMessageImpl implements StorageServiceMessageLocal {
	protected static final Logger logger = Logger.getLogger(StorageServiceMessageImpl.class);
	
	@PersistenceContext(unitName = "commentry-jpa")
	private EntityManager entityManager;
	
	@Resource
	SessionContext sessionContext;
	
	@SuppressWarnings("unchecked")
	public String createStorageServiceInfo(int userId, String orderCode, int groupId, int lockersId) {
		
		UserTransaction ut = sessionContext.getUserTransaction();
		
		try {
			ut.begin();

			/*List<StorageServiceInfo> oldStorageList = entityManager.createQuery("select ssi from StorageServiceInfo ssi where ssi.enable = true and purchaser.purchaserId = " + userId + " and ssi.lockers.lockersId = " + lockersId).getResultList();
			
			if (null != oldStorageList && oldStorageList.size() > 0){
				
				return oldStorageList.get(0).getStorageRfid();
			}*/ 
			
			List<StorageServiceInfo> storageServiceInfos = entityManager.createQuery("select ssi from StorageServiceInfo ssi where ssi.number = '" + orderCode + "' and ssi.groupId = " + groupId).getResultList();
			
			if (null != storageServiceInfos && storageServiceInfos.size() > 0){
				throw new Exception("Duplicate submit order! order code -> " + orderCode);
			}
			
			List<Lockers> lockersList = entityManager.createQuery("select l from Lockers l where l.storageBusiness = true and l.lockersId = " + lockersId).getResultList();
			
			if (null == lockersList || lockersList.size() == 0){
				throw new Exception("Lockers is not exist!");
			}
			
			Lockers lockers = lockersList.get(0);
			
			Purchaser purchaser = entityManager.find(Purchaser.class, userId);
			
			StorageServiceInfo storageServiceInfo = new StorageServiceInfo();
			
			autoCreateRfid(storageServiceInfo, lockers.getLockersSn());

			storageServiceInfo.setPurchaser(purchaser);
			storageServiceInfo.setLockers(lockers);
			storageServiceInfo.setGroupId(groupId);
			storageServiceInfo.setNumber(orderCode);
			storageServiceInfo.setEnable(true);
			storageServiceInfo.setInsertTime(new Date());
			
			entityManager.persist(storageServiceInfo);
			
			entityManager.flush();

			ut.commit();

			return storageServiceInfo.getStorageRfid();
		} catch (Exception e) {
			try {
				ut.rollback();
			} catch (Exception e1) {
				logger.error("Rollback fail\n" + e1.getMessage());
			}
			logger.error("Create storage service info fail!\n" + e.getMessage());
		} 

		return null;
	}

	@SuppressWarnings("unchecked")
	private void autoCreateRfid(StorageServiceInfo storageServiceInfo, String lockersSn){
		String rfid = randomRfid();
		
		rfid += CommEntryUtil.transferCheckBit(CommEntryUtil.getFormatStr(CRC8.getCRC(rfid, Integer.parseInt(lockersSn)), 2));
		
		String passwd = CommEntryUtil.confuse(calculatePasswd(CommEntryUtil.bernstein(rfid)));
		
		List<Object> rfidList = entityManager.createQuery("select ssi.storageRfid from StorageServiceInfo ssi where ssi.storageRfid = '" + rfid + "'").getResultList();
		
		if (null != rfidList && rfidList.size() > 0)
			autoCreateRfid(storageServiceInfo, lockersSn);
		
		List<Object> passwdList = entityManager.createQuery("select ssi.storageRfid from StorageServiceInfo ssi where ssi.enable = true and ssi.storagePasswd = '" + passwd + "'").getResultList();
		
		if (null != passwdList && passwdList.size() > 0)
			autoCreateRfid(storageServiceInfo, lockersSn);
		
		storageServiceInfo.setStorageRfid(rfid);
		storageServiceInfo.setStoragePasswd(passwd);
	}
	
	private String randomRfid() {
		String rfid = String.valueOf((long) (Math.random() * 1000000));

		while (rfid.length() < 6) {
			rfid += String.valueOf((long) (Math.random() * 10));
		}

		return rfid;
	}
	
	private String calculatePasswd(String rfid_sn) {
		StringBuffer sb = new StringBuffer();
		String done = rfid_sn.substring(7, 19);
		sb.append(done.charAt(3));
		sb.append(done.charAt(7));
		sb.append(done.charAt(4));
		sb.append(done.charAt(10));
		sb.append(done.charAt(2));
		sb.append(done.charAt(5));
		return sb.toString();
	}

	@SuppressWarnings("unchecked")
	public String queryStorageServiceInfo(int userId, int groupId) {
		JSONArray result = new JSONArray();
		
		List<StorageServiceInfo> storageServiceInfos = entityManager.createQuery("select ssi from StorageServiceInfo ssi where ssi.purchaser.purchaserId = " + userId + " and ssi.groupId = " + groupId + " order by ssi.insertTime desc").getResultList();
		
		for (StorageServiceInfo storageServiceInfo : storageServiceInfos) {
			JSONObject data = new JSONObject();
			data.accumulate("storage_code", storageServiceInfo.getStorageRfid());
			data.accumulate("store_order_code", storageServiceInfo.getNumber());
			data.accumulate("store_address", storageServiceInfo.getLockers().getLocation().getDescription() + storageServiceInfo.getLockers().getLockersName());
			data.accumulate("delivery_time", null == storageServiceInfo.getDeliveryTime() ? "" : DateTimeHelper.dateTimeToStr(storageServiceInfo.getDeliveryTime(), DateTimeHelper.DEFAULT_DATE_TIME_FORMAT));
			data.accumulate("takeout_time", null == storageServiceInfo.getTakeoutTime() ? "" : DateTimeHelper.dateTimeToStr(storageServiceInfo.getTakeoutTime(), DateTimeHelper.DEFAULT_DATE_TIME_FORMAT));
			data.accumulate("enable", storageServiceInfo.isEnable());
			data.accumulate("create_time", DateTimeHelper.dateTimeToStr(storageServiceInfo.getInsertTime(), DateTimeHelper.DEFAULT_DATE_TIME_FORMAT));
			
			result.add(data);
		}
		
		return result.toString();
	}
}
